/* GA_IPD.java
 * CAP 5512
 * HW3, group 2
 * 
 * Date/other stuff/etc.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;

public class GA_TLP4 extends FitnessFunction
{

   private String outputFile;
   private String net, input_routes, trafficlight, output;
   private Process p;
   private static Random randomGenerator = new Random();
   private int populationCount;

   public GA_TLP4()
   {
      name = "GA_TLP";
      randomGenerator.setSeed(Parameters.seed);
      populationCount = 0;
   }

   public void doRawFitness(Chromo X)
   {
	  boolean occupancyLimit = false;
	   
      //create the new traffic lights based on Chromo
      new CreateXMLFile(X);

      //run the SUMO simulation
      try
      {
         p = Runtime.getRuntime().exec(GenerateSUMOExcutionString());
      } catch (IOException e)
      {
         e.printStackTrace();
      }

      ProcessHandler inputStream = new ProcessHandler(p.getInputStream(), "INPUT");
      ProcessHandler errorStream = new ProcessHandler(p.getErrorStream(), "ERROR");
      inputStream.start();
      errorStream.start();

      try
      {
         p.waitFor();
      } catch (InterruptedException e)
      {
         e.printStackTrace();
      }

      //Process output
      ProcessXMLOutput xmlOut = new ProcessXMLOutput();

      //Calculate the fitness for the aggregate of the timing lights based on occupancy

      //Store simulation statistics
      X.meanWaitingTimeAllLanes = xmlOut.getWaitingTime();
      X.meanTravelTimeAllLanes  = xmlOut.getMeanTravelTime();
      X.meanTravelTime          = xmlOut.getLaneMeanTravelTime();
      X.meanDensity             = xmlOut.getMeanDensity();
      X.meanOccupancy           = xmlOut.getMeanOccupancy();
      X.meanWaitingTime         = xmlOut.getMeanWaitingTime();
      X.meanSpeed               = xmlOut.getMeanSpeed();
      X.vehiclesEntered         = xmlOut.getVehiclesEntered();
      X.vehiclesLeft            = xmlOut.getVehiclesLeft();
      X.meanNumberOfVehicles               = xmlOut.getAvgNumVehicles();
      X.meanTrafficVolumeCarsPerHour       = xmlOut.getAvgTrafficVolumeCarsPerHour();
      X.meanTrafficVolumeAtExitCarsPerHour = xmlOut.getAvgTrafficVolumeExitingLaneCarsPerHour();
      
      for(int i=0;i<X.meanOccupancy.length;i++){
    	  if(X.meanOccupancy[i] > 15.0){
    		  occupancyLimit = true;
    	  }
      }
      
      if(occupancyLimit){
    	   double randnum;
    	   
    	   //generate new random member
    	   for(int i = 0; i < X.chromoLength; i++){
				randnum = Search.r.nextDouble();
				if (randnum <= 0.5) X.chromo.set(i);
		   }
    	   
           //assign worst fitness to this new structure
           X.rawFitness = 99999999999999999.0;
      }else{
    	   X.rawFitness = (.3)*X.meanWaitingTimeAllLanes + (.5)*X.meanTravelTimeAllLanes;
      }
   }

   public void doPrintGenes(Chromo X, FileWriter output) throws java.io.IOException
   {

      // Print the genes in reverse order. Gene 0 is stored in the LSB position,
      // thus, if you print it starting with that gene, the bits won't reflect the actual
      // ordering within the representation
      for (int i = 0; i < Parameters.numGenes; i++)
      {
         Hwrite.right("\""+X.getGeneAlpha(i)+"\"", 100, output);
      }
      output.write(",");
      for (int i = 0; i < Parameters.numGenes; i++)
      {
         Hwrite.right(X.getIntGeneValue(i), 30, 4, output);
      }
      output.write(",");
      Hwrite.right(X.rawFitness, 12, 6, output);
      return;
   }


   //Generate Output file
   private String GenerateSUMOExcutionString()
   {
      String randomRouteFile = "";
      int randomFileNumber = 0;

      //Keeps the route size
      if (this.populationCount++ > Parameters.popSize)
      {
         randomFileNumber = this.randomGenerator.nextInt(4);
         this.populationCount = 0;
      }

      if (Parameters.isMacOS)
      {
         net = Parameters.sumoNetworkRoutePath + Parameters.sumoNetworkFile;

         if (Parameters.sumoRouteFile.equals("RANDOM"))
         {
            switch (randomFileNumber)
            {
               case 0:
                  randomRouteFile = "random1.rou.xml";
                  break;
               case 1:
                  randomRouteFile = "random2.rou.xml";
                  break;
               case 2:
                  randomRouteFile = "random3.rou.xml";
                  break;
               case 3:
                  randomRouteFile = "random4.rou.xml";
                  break;
               default:
                  System.out.println("\n\nERROR-No file for random int\n");
            }

            input_routes = Parameters.sumoNetworkRoutePath + randomRouteFile;
         } else
         {
            input_routes = Parameters.sumoNetworkRoutePath + Parameters.sumoRouteFile;
         }

         trafficlight = Parameters.sumoNetworkRoutePath + Parameters.sumoAdditionalParamFile;
         output = Parameters.sumoOutputPath + Parameters.sumoOutputFile;

         outputFile = Parameters.sumoBinPath + "sumo"
                 + " -b " + Parameters.sumoBeginTime
                 + " -e " + Parameters.sumoEndTime
                 + " -n " + net
                 + " -r " + input_routes
                 + " -a " + trafficlight
                 + " --emissions-output " + output
                 + " --time-to-teleport -1"; //Forces SUMO not to teleport vehicles

      } else
      {//Windows Machine
         net = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoNetworkFile + "\"";

         if (Parameters.sumoRouteFile.equals("RANDOM"))
         {
            switch (randomFileNumber)
            {
               case 0:
                  randomRouteFile = "random1.rou.xml";
                  break;
               case 1:
                  randomRouteFile = "random2.rou.xml";
                  break;
               case 2:
                  randomRouteFile = "random3.rou.xml";
                  break;
               case 3:
                  randomRouteFile = "random4.rou.xml";
                  break;
               default:
                  System.out.println("\n\nERROR-No file for random int\n");
            }

            input_routes = "\"" + Parameters.sumoNetworkRoutePath + randomRouteFile + "\"";
         } else
         {
            input_routes = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoRouteFile + "\"";
         }

         trafficlight = "\"" + Parameters.sumoNetworkRoutePath + Parameters.sumoAdditionalParamFile + "\"";
         output = "\"" + Parameters.sumoOutputPath + Parameters.sumoOutputFile + "\"";

         outputFile = "\"" + Parameters.sumoBinPath + "sumo.exe" + "\""
                 + " -b " + Parameters.sumoBeginTime
                 + " -e " + Parameters.sumoEndTime
                 + " -n " + net
                 + " -r " + input_routes
                 + " -a " + trafficlight
                 + " --emissions-output " + output
                 + " --time-to-teleport -1"; //Forces SUMO not to teleport vehicles.


      }//end if MAC or Windows

      //System.out.println("\n" + outputFile);
      return outputFile;
   }//end GenerateSUMOExcutionString

}
